package pool

// Pool common pool.
type Pool[T any] struct {
	pool      []T
	newFunc   func() T
	resetFunc func(*T)
	maxSize   int
}

// NewPool 创建泛型对象池
// newFunc: 创建新对象的函数
// resetFunc: 重置对象的函数
// maxSize: 对象池最大容量
func NewPool[T any](newFunc func() T, resetFunc func(*T), maxSize int) *Pool[T] {
	if maxSize <= 0 {
		maxSize = 1024
	}
	return &Pool[T]{
		pool:      make([]T, 0, maxSize/2),
		newFunc:   newFunc,
		resetFunc: resetFunc,
		maxSize:   maxSize,
	}
}

// Get 从对象池获取对象
func (p *Pool[T]) Get() T {
	if len(p.pool) == 0 {
		return p.newFunc()
	}

	// 从池中取出最后一个对象
	obj := p.pool[len(p.pool)-1]
	p.pool = p.pool[:len(p.pool)-1]
	return obj
}

// Put 将对象放回对象池
func (p *Pool[T]) Put(obj T) {
	// 重置对象状态
	if p.resetFunc != nil {
		p.resetFunc(&obj)
	}

	// 如果池已满，则丢弃对象
	if len(p.pool) >= p.maxSize {
		return
	}
	p.pool = append(p.pool, obj)
}

// Size 返回当前池中对象数量
func (p *Pool[T]) Size() int {
	return len(p.pool)
}

// Clear 清空对象池
func (p *Pool[T]) Clear() {
	p.pool = p.pool[:0]
}

// Cap 返回对象池容量
func (p *Pool[T]) Cap() int {
	return cap(p.pool)
}

// Preallocate 预分配对象
func (p *Pool[T]) Preallocate(count int) {
	if count <= 0 {
		return
	}

	// 确保不超过最大容量
	if count > p.maxSize {
		count = p.maxSize
	}

	// 确保不超过切片容量
	available := cap(p.pool) - len(p.pool)
	if count > available {
		newPool := make([]T, len(p.pool), len(p.pool)+count)
		copy(newPool, p.pool)
		p.pool = newPool
	}

	for i := 0; i < count && len(p.pool) < p.maxSize; i++ {
		p.pool = append(p.pool, p.newFunc())
	}
}
